﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
//using System.Text;

/// <summary>
/// Server class that listens for clients and returns the fibonacci number if possible
/// 
/// author: Charles Williams
/// version: 2011.9.20
/// </summary>
class server
{
    public static void Main()
    {
        Thread fthread = new Thread(spawnFibonacciThread);
        fthread.Start();
    }

    private static void spawnFibonacciThread()
    {
        TcpListener server = null;
        try
        {
            // Set the TcpListener on port 12000.
            Int32 port = 12000;
            IPAddress localAddr = IPAddress.Parse("127.0.0.1");

            // TcpListener server = new TcpListener(port);
            server = new TcpListener(localAddr, port);

            // Start listening for client requests.
            server.Start();

            // Enter the listening loop.
            while (true)
            {
                Console.Write("Waiting for a connection... ");

                // Perform a blocking call to accept requests.
                // You could also user server.AcceptSocket() here.

                TcpClient client = server.AcceptTcpClient();
                Console.WriteLine("Connected!");

                NetworkStream networkStream = client.GetStream();
                StreamWriter streamWriter = new StreamWriter(networkStream);
                StreamReader streamReader = new StreamReader(networkStream);
                string theString = "this is the string the server sent out";

                theString = streamReader.ReadLine();
                
                //Converts input to an int if possible.
                int input = Convert.ToInt32(theString);

                //Makes sure the input is positive.
                if (input < 0)
                {
                    throw new FormatException();
                }

                //Calculates the fibonacci number.
                int result = calculateFibonacci(input);

                //Sends the result back to the client.
                streamWriter.WriteLine(result);
                streamWriter.Flush();

                streamReader.Close();
                networkStream.Close();
                streamWriter.Close();

                // Shutdown and end connection
                client.Close();
            }
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
        }
        catch (FormatException f)
        {
            Console.WriteLine("Invalid input.");
        }
        catch (Exception e)
        {
            Console.WriteLine("An unknown error has ocurred");
        }
        finally
        {
            // Stop listening for new clients.
            server.Stop();
        }


        Console.WriteLine("\nHit enter to continue...");
        Console.Read();
    }

    /// <summary>
    /// Calculates the fibonacci number of the input value.
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private static int calculateFibonacci(int value)
    {
        int calculatedValue = 0;
        if(value == 0 || value == 1)
        {
            calculatedValue = value;
        }
        else
        {
            calculatedValue = calculateFibonacci(value - 1) + calculateFibonacci(value - 2);
        }

        return calculatedValue;
    }

}

